#pragma once
#include<iostream>
#include<string>
#include<cerrno>
#include<cstring>
#include<cstdlib>
#include<strings.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include"Log.hpp"
#include"InetAddr.hpp"
enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR
};
const static int defaultfd = -1;

class UdpServer
{
    public:
    UdpServer(uint16_t port)
    :_sockfd(defaultfd)
    ,_port(port)
    ,_isrunning(false)
    {}
    void InitServer()
    {
        //创建udp socket 套接字，----必须要做的
        _sockfd = socket(AF_INET,SOCK_DGRAM,0); 
        if(_sockfd<0)
        {
            //失败的信息
            LOG(FATAL,"socket error,%s,%d\n",strerror(errno),errno);
            exit(SOCKET_ERROR);
        }
        //成功
        LOG(INFO,"socket create success, sockfd:%d\n",_sockfd);
        //填充sockaddr_in的结构；
        struct sockaddr_in local;
        bzero(&local,sizeof(local));//初始化
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);//port要经过网络传输给对面，主力序列转成网络序列
        local.sin_addr.s_addr = INADDR_ANY;
        //绑定
        int n = bind(_sockfd,(struct sockaddr *)&local,sizeof(local));
        if(n<0)
        {
            LOG(FATAL,"bind error ,%s,%d\n",strerror(errno),errno);
            exit(BIND_ERROR);
        }
        LOG(INFO,"socket bind success\n");

    }
    void Start()
    {
        //运行
        _isrunning = true;
        while (true)
        {
            char buffer[1024];
            struct sockaddr_in peer;
            socklen_t  len = sizeof(peer);
            //1:先让服务端收集数据
            ssize_t n = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
            if(n>0)
            {
                buffer[n] = 0;
                InetAddr addr(peer);
                LOG(DEBUG,"get message from[%s:%d]:%s\n",addr.Ip().c_str(),addr.Port(),buffer);
                sendto(_sockfd,buffer,sizeof(buffer),0,(struct sockaddr *)&peer,len);
            }
        }
        _isrunning = false;
    }
    ~UdpServer()
    {}
    private:
    int _sockfd;
    uint16_t _port;
    bool _isrunning;
};